import requests
from pathlib import Path
from datetime import datetime
from requests_toolbelt.multipart.encoder import MultipartEncoder
import re
import time

class EventUploader:
    def __init__(self):
        self.time_format = "%Y%m%d_%H%M%S"  # 时间戳解析格式
        self.max_retries = 3                 # 失败重试次数
        self.retry_delay = 2                 # 重试间隔（秒）

    def upload_images(self, source_dir: str, api_url: str, camera_name: str, video_name: str, algorithm_id: str):
        """上传目录下所有图片"""
        result = {"total": 0, "success": 0, "failed": []}

        try:
            # 验证并格式化API地址
            api_url = self._validate_url(api_url)

            # 获取并排序源图片
            image_files = sorted(
                Path(source_dir).glob("*.jpg"),
                key=self._extract_timestamp
            )

            # 调用上传方法
            batch_result = self._upload_batch(
                image_files, api_url, camera_name,
                video_name, algorithm_id
            )
            result["total"] += len(image_files)
            result["success"] += batch_result["success"]
            result["failed"].extend(batch_result["failed"])

        except Exception as e:
            print(f"初始化错误: {str(e)}")

        return result

    def _upload_batch(self, batch: list, api_url: str,
                      camera_name: str, video_name: str, algorithm_id: str) -> dict:
        """批量上传逻辑"""
        batch_result = {"success": 0, "failed": []}

        for attempt in range(self.max_retries):
            try:
                # 准备多部分数据
                fields = {
                    "cameraName": camera_name,
                    "videoName": video_name,
                    "algorithmId": algorithm_id
                }

                # 添加图片数组字段
                for idx, img_path in enumerate(batch):
                    fields[f"images[{idx}].name"] = img_path.name
                    fields[f"images[{idx}].time"] = self._parse_timestamp(img_path).isoformat()
                    fields[f"images[{idx}].file"] = (img_path.name, open(img_path, "rb"), "image/jpeg")

                # 构建编码器
                encoder = MultipartEncoder(fields=fields)

                # 发送请求
                response = requests.post(
                    api_url,
                    data=encoder,
                    headers={"Content-Type": encoder.content_type},
                    timeout=(100, 3000)
                )

                # 处理响应
                if response.status_code == 200:
                    success_count = self._parse_response(response.json(), batch)
                    batch_result["success"] = success_count
                    batch_result["failed"] = [p.name for p in batch if p.name not in [x.name for x in batch[:success_count]]]
                    print(f"批量上传 {len(batch)}")
                    return batch_result
                else:
                    print(f"尝试 {attempt + 1} 失败，状态码: {response.status_code}")

            except requests.exceptions.RequestException as e:
                print(f"网络错误: {str(e)}")
            except Exception as e:
                print(f"处理错误: {str(e)}")
                batch_result["failed"].extend([p.name for p in batch])
            finally:
                # 关闭所有文件句柄
                for f in fields.values():
                    if isinstance(f, tuple) and not f[1].closed:
                        f[1].close()

            if attempt < self.max_retries - 1:
                time.sleep(self.retry_delay)

        # 所有重试失败
        batch_result["failed"].extend([p.name for p in batch])
        return batch_result

    def _parse_response(self, response_json: dict, batch: list) -> int:
        """解析批量响应（示例解析逻辑）"""
        if response_json.get("code") == 200:
            return len([p for p in batch if p.name in response_json["data"]["success"]])
        return 0

    def _validate_url(self, url: str) -> str:
        """标准化API地址格式"""
        url = url.replace("http://http://", "http://").replace("https://https://", "https://")
        if not url.startswith(("http://", "https://")):
            url = f"http://{url}"
        return url.rstrip('/')

    def _extract_timestamp(self, path: Path) -> int:
        """从文件名提取排序数字"""
        try:
            return int(re.findall(r'\d+', path.stem)[-1])
        except:
            return 0

    def _parse_timestamp(self, path: Path) -> datetime:
        """解析图片时间戳"""
        try:
            parts = path.stem.split('_')
            if len(parts) >= 2:
                return datetime.strptime('_'.join(parts[-2:]), self.time_format)
        except:
            pass
        return datetime.fromtimestamp(path.stat().st_mtime)

# if __name__ == "__main__":
#     uploader = EventUploader()
#     report = uploader.upload_images(
#         source_dir="/data/control_communication/keyuan/keyuan",
#         api_url="http://192.168.0.142:80/aiApi/saveEvent",
#         camera_name="keyuan",
#         video_name="keyuan",
#         algorithm_id="1"
#     )

    # print(f"总上传结果: 成功 {report['success']} 张，失败 {len(report['failed'])} 张")
    